﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 原型模式好处在于对于相同（或者大部分相似）的对象，
/// 我们创建它们的时候，并不需要考虑每一个对象的每一个细节。
/// 并且可以创建一个对象的副本，在有限的范围内修改这个副本不会影响原对象。
/// 
/// 坏处就在于，我们需要实现复杂的Clone方法，
/// 需要避免多余的深表复制（浪费内存），
/// 尤其要注意循环引用的情况（例如A引用B，B再引用A，这样会造成死循环）。
/// </summary>
public class AnimalPrototypeTest : ICloneable
{
    /// 使用.Net为我们提供的ICloneable接口（这个接口经常见到啊！原来还是一种设计模式！突然感觉高贵冷艳了起来。）：

    public string name { get; set; }
    public int hp { get; set; }
    public AnimalPrototypeTest(string name_)
    {
        name = name_;
    }
    public override string ToString()
    {
        return string.Format("[Animal: name={0}, hp={1}]", name, hp);
    }
    public virtual object Clone()
    {
        return (object)this.MemberwiseClone();
    }

}



public class AnimalSkill : ICloneable
{
    public string skillName { get; set; }
    public int skillAttack { get; set; }
    public object Clone()
    {
        return (object)this.MemberwiseClone();
    }
    public override string ToString()
    {
        return string.Format("[AnimalSkill: skillName={0}, skillAttack={1}]", skillName, skillAttack);
    }
}

public class SkillAnimalPrototype : AnimalPrototypeTest
{
    private AnimalSkill _skill;
    public AnimalSkill skill { get { return _skill; } }
    public SkillAnimalPrototype(string name_) : base(name_)
    {
        _skill = new AnimalSkill();
    }
    public void SetSkillInfo(string name_, int attack_)
    {
        _skill.skillName = name_;
        _skill.skillAttack = attack_;
    }
    //public override object Clone()
    //{
    //    return (object)this.MemberwiseClone();
    //}
    public override object Clone()
    {
        SkillAnimalPrototype ret = (SkillAnimalPrototype)base.Clone();
        ret._skill = (AnimalSkill)_skill.Clone();
        return ret;
    }
    public override string ToString()
    {
        return base.ToString() + skill.ToString();
    }
}

public class AnimalPrototype:MonoBehaviour
{
    private void Start()
    {
        //AnimalPrototypeTest animalPrototypeTest = new AnimalPrototypeTest("wofule");
        //animalPrototypeTest.hp = 80;

        //AnimalPrototypeTest test02 = (AnimalPrototypeTest)animalPrototypeTest.Clone();
        //test02.hp = 100;
        //Debug.Log(animalPrototypeTest == test02);
        //Debug.Log(animalPrototypeTest.ToString());
        //Debug.Log(test02.ToString());

        SkillAnimalPrototype skillAnimalPrototype = new SkillAnimalPrototype("skillAnimalPrototype");
        skillAnimalPrototype.SetSkillInfo("recive", 0);
        SkillAnimalPrototype skillAnimalPrototype2 = (SkillAnimalPrototype)skillAnimalPrototype.Clone();
        skillAnimalPrototype2.name = "skillAnimalPrototype2";
        skillAnimalPrototype2.SetSkillInfo("fire", 20);

        Debug.Log(skillAnimalPrototype);
        Debug.Log(skillAnimalPrototype2);
    }
}
